package form.ui.component.Slider
{
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	
	import form.dispatchers.FormElementDispatcher;
	import form.events.FormElementChangeEvent;
	import form.events.FormElementEvent;
	import form.events.SliderEvent;
	import form.interfaces.IFormElement;
	import form.ui.core.FMSprite;
	import form.ui.core.IDirectionAble;
	import form.utils.MathUtils;
		
	public class Slider extends FMSprite implements IFormElement, IDirectionAble
	{
		public static const HORIZONTAL:String = "horizontal";
		public static const VERTICAL:String = "vertical";
		
		public static const DEFAULT_WIDTH:uint = 100;
		public static const DEFAULT_HEIGHT:uint = 12;
		
		public var showHighLight:Boolean = true;
		public var showProgress:Boolean = true;
		public var clickAble:Boolean = true;
		public var liveDrag:Boolean = false;
				
		protected var thumb:SlideThumb;
		protected var track:SliderTrackSkin;
		protected var highlightTrack:SliderHighlightSkin;
		protected var progressTrack:SliderHighlightSkin;
		
		private var hitAreaUI:Sprite;
		private var innerSlide:Sprite;
		
		public function Slider()
		{
			super();
			
			hitAreaUI = new Sprite();
			hitAreaUI.mouseEnabled = false;
			hitAreaUI.mouseChildren = false;			
			
			innerSlide = new Sprite();
			innerSlide.buttonMode = true;
			innerSlide.hitArea = hitAreaUI;
			track = new SliderTrackSkin();
			
			thumb = new SlideThumb(this);			
			thumb.addEventListener(SliderEvent.SLIDE_CHANGE, onSlideThumbChange, false, 0, true);
			thumb.addEventListener(MouseEvent.MOUSE_DOWN, onThumbPress, false, 0, true);
			thumb.addEventListener(SliderEvent.THUMB_RELEASE, onThumbRelease, false, 0, true);
			
			highlightTrack = new SliderHighlightSkin();
			highlightTrack.themeColor = highLightColor;
			highlightTrack.width = 0;
				
			progressTrack = new SliderHighlightSkin();
			progressTrack.themeColor = progressColor;
			progressTrack.width = 0;
								
			addChild(hitAreaUI);
			addChild(innerSlide);		
			innerSlide.addChild(track);			
			innerSlide.addChild(progressTrack);
			innerSlide.addChild(highlightTrack);
			innerSlide.addChild(thumb);
			
			this.registerStyle("thumbUpSkin");
			this.registerStyle("thumbOverSkin");
			this.registerStyle("thumbDownSkin");
			this.registerStyle("thumbDisableSkin");
			
			if(!showHighLight)highlightTrack.visible = false;			
			if(!showProgress)progressTrack.visible = false;			
			this.addEventListener(MouseEvent.CLICK, onMouseClick, false, 0, true);
			
			var e:FormElementEvent = new FormElementEvent(FormElementEvent.INITIALIZED);
			e.element = this;
			FormElementDispatcher.instance.dispatchEvent(e);
		}
		
		private var _direction:String;
		public function get direction():String
		{
			return _direction;
		}
		public function set direction(value:String):void
		{
			_direction = value;
			if(isHorization)
			{
				innerSlide.rotation = 0;
				innerSlide.y = paddingTop;
				if(this.width < DEFAULT_WIDTH) this.width = DEFAULT_WIDTH;
				this.height = DEFAULT_HEIGHT;
			}
			else
			{
				innerSlide.rotation = -90;			
				if(this.height < DEFAULT_WIDTH)this.height = DEFAULT_WIDTH;
				this.width = DEFAULT_HEIGHT;
				innerSlide.y = paddingTop + this.height;
			}
			
			this.draw();
		}
		
		private var _highLightColor:uint = 0xFFFFFF;
		public function get highLightColor():uint
		{
			return _highLightColor;
		}
		public function set highLightColor(value:uint):void
		{
			_highLightColor = value;
		}
		
		private var _progressColor:uint = 0xFFCC00;
		public function get progressColor():uint
		{
			return _progressColor;
		}
		public function set progressColor(value:uint):void
		{
			_progressColor = value;
		}
		
		public function get thumbUpSkin():String
		{
			return thumb.upSkin;
		}
		public function set thumbUpSkin(value:String):void
		{
			thumb.upSkin = value;
		}
		
		public function get thumbOverSkin():String
		{
			return thumb.overSkin;
		}
		public function set thumbOverSkin(value:String):void
		{
			thumb.overSkin = value;
		}
		
		public function get thumbDownSkin():String
		{
			return thumb.downSkin;
		}
		public function set thumbDownSkin(value:String):void
		{
			thumb.downSkin = value;
		}
		
		public function get thumbDisableSkin():String
		{
			return thumb.disabledSkin;
		}
		public function set thumbDisableSkin(value:String):void
		{
			thumb.disabledSkin = value;
		}
		
		private function onThumbPress(e:MouseEvent):void
		{
			dispatchEvent(new SliderEvent(SliderEvent.THUMB_PRESS, this.measuredValue));
		}
		
		private function onThumbRelease(e:SliderEvent):void
		{
			dispatchEvent(new SliderEvent(SliderEvent.THUMB_RELEASE, this.measuredValue));
			setEventValue(e.value);
		}
		
		private function setEventValue(value:Number):void
		{
			value = MathUtils.constrain(value);
			this.value = value;
			this.formValue = value.toString();
		}
		
		private function onSlideThumbChange(e:SliderEvent):void
		{
			liveDrag ? setEventValue(e.value) : value = e.value;
		}
		
		private function onMouseClick(e:MouseEvent):void
		{
			if(clickAble && e.target == this.innerSlide)
			{
				setEventValue(MathUtils.reangleToPoint(track.x, trackLength + track.x, e.localX));
				dispatchEvent(new SliderEvent(SliderEvent.THUMB_RELEASE, this.measuredValue));
			}
		}
		
		private var _dragRect:Rectangle = new Rectangle();
		public function get dragRect():Rectangle
		{
			_dragRect.x = innerSlide.x;
			_dragRect.width = trackLength;
			return _dragRect;
		}
		
		private var _formName:String;		
		public function set formName(value:String):void
		{
			_formName = value;
		}
		
		public function get formName():String
		{
			return _formName;
		}
		
		private var _formValue:String;
		public function set formValue(value:String):void
		{
			_formValue = value;
			var evt:FormElementChangeEvent = new FormElementChangeEvent(FormElementChangeEvent.SLIDE_CHANFGE);
			evt.element = this;
			dispatchEvent(evt);
		}		
		public function get formValue():String
		{
			return _formValue;
		}
		
		private var _value:Number = 0;
		public function set value(val:Number):void
		{
			val = isNaN(val) ? 0 : val;
			if(val < 0) val = 0;
			if(_value != val)
			{
				_value = val;
				updateValue();
			}			
		}		
		public function get value():Number
		{
			return _value;			
		}
		
		public function get measuredValue():Number
		{
			return _value * this.maximum - this.minimum;
		}

	    private var _maximum:Number = 10;	
	    public function get maximum():Number
	    {
	        return _maximum;
	    }
	    public function set maximum(value:Number):void
	    {
	        _maximum = value;
	    }
	
	    private var _minimum:Number = 0;
	    public function get minimum():Number
	    {
	        return _minimum;
	    }	
	    public function set minimum(value:Number):void
	    {
	        _minimum = value;
	    }
		
		public function enable():void
		{
			thumb.enable();
		}
		
		public function disable():void
		{
			thumb.disable();
		}
		
		private var progressValue:Number = 0;
		public function setProgress(percent:Number):void
		{
			percent = MathUtils.constrain(percent);
			progressValue = isNaN(percent) ? 0 : percent;
			if(showProgress)updateValue();
		}
		
		private function drawHitArea():void
		{
			if(hitAreaUI)
			{
				hitAreaUI.graphics.clear();
				hitAreaUI.graphics.beginFill(0, 0);
				hitAreaUI.graphics.drawRect(0, 0, this.width, this.height);
				hitAreaUI.graphics.endFill();
			}
			
		}
		
		private function updateValue():void
		{
			if(showProgress && progressTrack)progressTrack.width = progressValue * trackLength;			
			if(showHighLight && highlightTrack)highlightTrack.width = value * trackLength;
			if(thumb)
			{
				 var thumbX:Number = value * trackLength;
				if(thumb.x != thumbX) thumb.x = thumbX	 						
			} 
		}
		
		override public function draw():void
		{
			super.draw();
			if(!track) return;
			innerSlide.x = paddingLeft;
						
			track.x = thumb.width / 2;
			track.y = thumb.height / 2 - track.height / 2;					
			
			highlightTrack.x = track.x;
			highlightTrack.y = track.y + 1;	
			
			progressTrack.x = highlightTrack.x;
			progressTrack.y = highlightTrack.y;
			
			drawHitArea();
			
			updateValue();
		}
		
		override public function set width(value:Number):void
		{
			super.width = value;
			if(isHorization && track.width != trackLength)
			{
				track.width = trackLength;
				draw();
			}
			
		}
		
		override public function set height(value:Number):void
		{
			super.height = value;
			if(!isHorization && track.width != trackLength)
			{
				track.width = trackLength;
				draw();
			}
		}
		
		private function get trackLength():Number
		{
			var max:Number = isHorization ? this.width : this.height;
			return max - this.thumb.width - this.paddingLeft - this.paddingLeft;
		}
		
		private function get isHorization():Boolean
		{
			return direction == HORIZONTAL;			
		}
	}
}